/******************************************************************************
 * Copyright 2022 The Airos Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file     device_base.h
 * @brief    相机设备接口
 * @version  V1.0.0
 */

#pragma once

#include <functional>
#include <memory>
#include <string>

namespace os {
namespace v2x {
namespace device {

/**
 * @struct  ImageMode
 * @brief   图像模式
 * @details
 */
enum class ImageMode { RGB, BGR, GRAY, YUV };

/**
 * @struct  ImageDeviceType
 * @brief   GPU设备类型
 * @details
 */
enum class ImageDeviceType { CPU, NVIDIA_GPU, KUNLUN_XPU };

enum class CameraDeviceType { IPCAMERA, CAMERA };

/**
 * @struct  CameraDeviceState
 * @brief   相机设备状态
 * @details
 */
enum class CameraDeviceState { UNKNOWN, RUNNING, STOP, NO_REGISTER };

/**
 * @struct  HWMemory
 * @brief   设备内存
 * @details
 */
class HWMemory {
 public:
  using Alloter = void* (*)(size_t);
  using Deleter = void (*)(void*);

  HWMemory(Alloter alloter, size_t size, Deleter deleter)
      : alloter_(alloter), deleter_(deleter), data_(nullptr), size_(0) {
    if (size > 0) {
      data_ = alloter_(size);
      if (data_) {
        size_ = size;
      }
    }
  }

  ~HWMemory() {
    if (data_) {
      deleter_(data_);
      data_ = nullptr;
    }
  }

  const void* data() const { return data_; }
  void* mutable_data() { return data_; }
  size_t size() const { return size_; }

  HWMemory(const HWMemory&) = delete;
  HWMemory& operator=(const HWMemory&) = delete;
  HWMemory(HWMemory&&) = delete;
  HWMemory& operator=(HWMemory&&) = delete;

 private:
  Alloter alloter_;
  Deleter deleter_;
  void* data_;
  size_t size_;
};

/**
 * @struct  CameraData
 * @brief   AirOS-edge结构化的标准相机输出数据
 * @details
 */
struct CameraData {
  std::shared_ptr<HWMemory> image;  ///<图片指针
  ImageDeviceType device_type;      ///<图片所在设备类型
  uint32_t device_id;               ///<设备ID
  CameraDeviceType camera_type;     ///<相机类型
  std::string camera_name;          ///<相机名称
  ImageMode mode;                   ///<图像模式
  uint32_t height;                  ///<高度
  uint32_t width;                   ///<宽度
  uint64_t timestamp;               ///<时间戳
  uint32_t sequence_num;            ///<序列号
};

using CameraStreamCallBack = std::function<void(
    const std::string& camera_name, const uint8_t* data, size_t size)>;

/**
 * @brief  相机接口类
 */
class CameraDevice {
 public:
  CameraDevice() = default;
  explicit CameraDevice(const CameraStreamCallBack& cb) : stream_sender_(cb) {}
  virtual ~CameraDevice() = default;
  /**
   * @brief      用于相机初始化
   * @param[in]  config_file 相机初始化参数配置文件
   * @retval     初始化是否成功
   */
  virtual bool Init(const std::string& config_file) = 0;
  /**
   * @brief      用于获取指定的相机的图片数据
   * @param[in]  camera_name 指定相机名称
   * @retval     AirOS-edge结构化的标准相机输出数据
   */
  virtual std::shared_ptr<CameraData> GetImage(
      const std::string& camera_name) = 0;
  /**
   * @brief      用于获取相机设备状态
   * @retval     设备状态码CameraDeviceState
   */
  virtual CameraDeviceState GetState(const std::string& camera_name) = 0;

 protected:
  CameraStreamCallBack stream_sender_;
};

}  // namespace device
}  // namespace v2x
}  // namespace os